package calendar

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"sync"
	"time"
	"unsafe"
)

var (
	mutex      = sync.RWMutex{}
	holidayMap = map[int]*holiday{}
)

type holiday struct {
	year int
	days map[string]bool
}

func (h *holiday) Is(t *time.Time) bool {
	day := t.Format("2006-01-02")
	if b, ok := h.days[day]; ok {
		return b
	}
	weekday := t.Weekday()
	if weekday == time.Sunday || weekday == time.Saturday {
		return true
	}
	return true
}

func init() {
	t := time.Now()
	loadYear(t.Year())
}

func loadYear(year int) *holiday {
	mutex.RLock()
	if h, ok := holidayMap[year]; ok {
		mutex.RUnlock()
		return h
	}
	mutex.RUnlock()
	mutex.Lock()
	if h, ok := holidayMap[year]; ok {
		mutex.Unlock()
		return h
	}
	h := &holiday{
		year: year,
		days: map[string]bool{},
	}
	holidayMap[year] = h
	_ = loadYearBaidu(h)
	mutex.Unlock()
	return h
}

type baiduResult struct {
	Data []struct {
		Holiday []struct {
			List []struct {
				Date   string `json:"date"`
				Status string `json:"status"`
			} `json:"list"`
		} `json:"holiday"`
	} `json:"data"`
}

func loadYearBaidu(h *holiday) error {
	// 根据百度接口
	resp, err := http.Get("https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query=" + url.QueryEscape(fmt.Sprintf("%d年%d月", h.year, 1)) + "&co=&resource_id=6018&t=1578357406127&ie=utf8&oe=gbk&cb=op_aladdin_callback&format=json&tn=baidu&cb=jQuery11020002977011609388569_1578357382912&_=1578357382916")
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	d := bytes2str(body)
	d = d[len("/**/jQuery11020002977011609388569_1578357382912("):]
	d = d[:len(d)-2]
	var result baiduResult
	if err := json.Unmarshal(str2bytes(d), &result); err != nil {
		return err
	}
	for _, v := range result.Data {
		for _, vv := range v.Holiday {
			for _, vvv := range vv.List {
				b := true
				if vvv.Status == "2" {
					b = false
				}
				h.days[vvv.Date] = b
			}
		}
	}
	return nil
}

func IsHoliday(t *time.Time) bool {
	h := loadYear(t.Year())
	return h.Is(t)
	//// 周末
	//weekday := t.Weekday()
	//if weekday == time.Sunday || weekday == time.Saturday {
	//	return true
	//}
	//month := t.Month()
	//day := t.Day()
	//lunar := NewLunar(t)
	//
	////元旦，放假1天(1月1日)；
	//if month == 1 && day == 1 {
	//	return true
	//}
	////（二）春节，放假3天(农历正月初一、初二、初三)；
	//if lunar.GetMonth() == 1 && (lunar.GetDay() == 1 || lunar.GetDay() == 2 || lunar.GetDay() == 3) {
	//	return true
	//}
	////（三）清明节，放假1天(公历清明当日)；
	//
	////（四）劳动节，放假1天(5月1日)；
	////（五）端午节，放假1天(农历端午当日)；
	////（六）中秋节，放假1天(农历中秋当日)；
	////（七）国庆节，放假3天(10月1日、2日、3日)。
	//return false
}
func bytes2str(b []byte) string {
	return *(*string)(unsafe.Pointer(&b))
}
func str2bytes(s string) []byte {
	x := (*[2]uintptr)(unsafe.Pointer(&s))
	h := [3]uintptr{x[0], x[1], x[1]}
	return *(*[]byte)(unsafe.Pointer(&h))
}
